﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace Sunny.Lib
{
    public class ProcessHelper
    {
        private static string traceTag;
        public static string TraceTag
        {
            get
            {
                if (string.IsNullOrEmpty(traceTag))
                {
                    traceTag = typeof(ProcessHelper).FullName;
                }
                return traceTag;
            }
        }

        public static Process StartTool(StartToolInfo startTool, bool multiEnabled = true, string argu = null)
        {
            // Judge if the tool have aready start.
            Process[] processes = GetProcessByProcessName(startTool.ToolName);
            if (!multiEnabled)
            {
                if (processes.Count() > 0)
                {
                    return processes[0];
                }
            }

            //System.Security.SecureString securePassword = new System.Security.SecureString();
            //Microsoft.Scs.Test.Common.Sequence.ForEach(PassWord, securePassword.AppendChar);

            //string filePath = Environment.ExpandEnvironmentVariables(@"%ProgramFiles%\Microsoft SPS\PaymentGateway\SolutionProvider\ProviderStatusInquiryTool\Microsoft.SolutionProvider.Adapters.ProviderPaymentStatusQueryTool.exe");
            //System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(filePath);
            //psi.Arguments = string.Format("/action mrn:\"{0}\" providerName:\"{1}\" report:true", mrn, adapterName);
            //System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(@"cmd.exe");
            //psi.Arguments = string.Format("/k \"D:\\\"Program Files (x86)\"\\\"Microsoft SPS\"\\PaymentGateway\\SolutionProvider\\ProviderStatusInquiryTool\\Microsoft.SolutionProvider.Adapters.ProviderPaymentStatusQueryTool.exe /action mrn:\"{0}\" providerName:\"{1}\"", mrn, adapterName);
            string toolPath = System.IO.Path.Combine(startTool.ToolPath, startTool.ToolName );
            System.IO.FileInfo file = new System.IO.FileInfo(toolPath);
            if (!file.Exists)
            {
                Logger.LogEvent(string.Format("{0} not exist.", toolPath));
                return null;
            }
            System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(toolPath);
            psi.Arguments = argu;
            //psi.UserName = UserName;
            //psi.Password = securePassword;
            //psi.Domain = Domain;
            psi.UseShellExecute = true;

            Process proc = Process.Start(psi);

            //proc.WaitForExit();
            proc.Close();
            proc.Dispose();

            return proc;
        }

        public static ResultMessage EndToolProcessById(int id)
        {
            ResultMessage result = null;
            Process proc = null;

            try
            {
                proc = Process.GetProcessById(id);
            }
            catch (ArgumentException ex)
            {
                result = new ResultMessage();
                result.Status = ResultStatus.Failed;
                result.ResultDescription += TraceTag + "Can't found the process by Id.\n";
                result.ResultDescription += ex.StackTrace;
                return result;
            }

            result = EndToolProcess(proc);

            return result;
        }

        public static ResultMessage EndToolProcessByToolName(string toolName)
        {
            ResultMessage result = new ResultMessage();
            string processName = "";

            if (string.IsNullOrEmpty(toolName))
            {
                result.Status = ResultStatus.Failed;
                result.ResultDescription += TraceTag + "tool name" + CommonErrorConstants.NullOrEmpty + "\n";
            }
            else
            {
                processName = toolName;
            }

            Process[] procs = Process.GetProcessesByName(processName);

            int counter = 0;
            foreach (var proc in procs)
            {
                if (EndToolProcess(proc).Status == ResultStatus.Failed)
                {
                    counter++;
                }
            }

            if (counter > 0)
            {
                result.Status = ResultStatus.Failed;
                result.ResultDescription = string.Format("{0} process kill failed.", counter);
            }
            else
            {
                result.Status = ResultStatus.Success;
            }

            return result;
        }

        public static ResultMessage EndToolProcess(Process proc)
        {
            ResultMessage result = new ResultMessage();

            try
            {
                proc.Kill();
                result.Status = ResultStatus.Success;
            }
            catch (Exception ex)
            {
                result.Status = ResultStatus.Failed;
                result.ResultDescription += TraceTag + "Kill the Process failed.\n";
                result.ResultDescription += ex.StackTrace;
            }

            return result;
        }

        public static Process[] GetProcessByProcessName(string processName)
        {
            Process[] processList = Process.GetProcessesByName(processName);
            return processList;
        }
    }

    [Serializable]
    public class StartToolInfo
    {
        private static string traceTag;
        public static string TraceTag
        {
            get
            {
                if (string.IsNullOrEmpty(traceTag))
                {
                    traceTag = typeof(StartToolInfo).FullName;
                }
                return traceTag;
            }
        }

        // The user of use to start specified tool
        public string UserName { get; set; }

        // The password of User
        public string PassWord { get; set; }

        // Server
        public string Domain { get; set; }

        // The name of start tool 
        public string ToolName { get; set; }

        // The path of start tool 
        public string ToolPath { get; set; }

        public StartToolInfo()
        {
        }

        public StartToolInfo(string toolName, string toolPath)
        {
            if (string.IsNullOrEmpty(toolName))
            {
                Logger.LogEvent("ToolName could not be null or empty.");
            }

            if (string.IsNullOrEmpty(toolPath))
            {
                Logger.LogEvent("ToolPath could not be null or empty.");
            }

            this.ToolName = toolName;
            this.ToolPath = toolPath;
        }
    }
}
